package cn.itsource.hrm.service.impl;

import cn.itsource.feign.client.RedisFeignClient;
import cn.itsource.hrm.config.ImageCodeProperties;
import cn.itsource.hrm.dto.SendSMSDto;
import cn.itsource.hrm.service.IVerifyCodeService;
import cn.itsource.hrm.utils.AjaxResult;
import cn.itsource.hrm.utils.HttpUtil;
import cn.itsource.hrm.utils.StrUtils;
import cn.itsource.hrm.utils.VerifyCodeUtils;
import cn.itsource.hrm.vo.SendSmsCodeVo;
import com.alibaba.fastjson.JSON;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.UUID;
@Service
public class IVerifyCodeServiceImpl implements IVerifyCodeService {

    @Autowired
    private RedisFeignClient redisFeignClient ;

    @Autowired
    private ImageCodeProperties imageCodeProperties;
    //图片验证码
    @Override
    public String creatImageCode(String imageKey) {
        //参数判断
        if(StringUtils.isBlank(imageKey)){
            throw new RuntimeException("无效的验证码的Key");
        }
        //1.后端接收到imageKey,通过工具类生成随机数据
        String substring = UUID.randomUUID().toString().substring(0, imageCodeProperties.getLength());
        //2.把验证码的值存储到Redis,要以前端传入的key去存
        //设置过期时间
        AjaxResult imageCodeResult = redisFeignClient.setex(imageKey, imageCodeProperties.getTimeout(), substring);
        if(!imageCodeResult.isSuccess()){
            throw new RuntimeException("图片验证码创建失败");
        }
        //3.把图片验证码的值合并图片
        String verifyCode = VerifyCodeUtils.verifyCode(
                imageCodeProperties.getWidth(),
                imageCodeProperties.getHeight(),
                substring);

        //4.返回图片响应给前端
        return verifyCode ;
    }


    //手机验证码
    @Override
    public void sendSmsCode(SendSMSDto sendSMSDto) {

        //从前端获取数据
        //用户输入的图片验证码
        String imageCode = sendSMSDto.getImageCode();
        //图片验证码的key
        String imageCodeKey = sendSMSDto.getImageCodeKey();
        //手机号
        String mobile = sendSMSDto.getMobile();

        if(StringUtils.isBlank(imageCodeKey) || StringUtils.isBlank(imageCode) || StringUtils.isBlank(mobile)){
            throw new RuntimeException("无效的手机验证码或图片验证码");
        }

        //用redis中的验证码和输入的验证码作比较
        AjaxResult ajaxResult = redisFeignClient.get(imageCodeKey);
        if(!ajaxResult.isSuccess() || ajaxResult.getResultObj() == null){
            throw new RuntimeException("无效的图片验证码,请重新填写");
        }
        //获取Redis中的图片验证码
        String imgeCodeFromRedis = ajaxResult.getResultObj().toString();
        if(!imgeCodeFromRedis.toLowerCase().equals(imageCode.toLowerCase())){
            throw new RuntimeException("图片验证码错误,请重新填写");
        }

        //后端判断Redis是否已经有一个有效的验证码
        String smsCodeKey ="REGISTER:SMS:"+mobile;

        //发送短信验证码时间
        Date now = new Date( );

        //得到验证码
        String smsCodeValue = null;
        //获取上一次的验证码发送记录
        AjaxResult smsCodelLastAjaxResult = redisFeignClient.get(smsCodeKey);
        if(smsCodelLastAjaxResult.isSuccess() && smsCodelLastAjaxResult.getResultObj() != null){
            //获取Redis中的发送记录
            String lastSendSmsCodeVoJson = smsCodelLastAjaxResult.getResultObj().toString();
            SendSmsCodeVo sendSmsCodeVo = JSON.parseObject(lastSendSmsCodeVoJson, SendSmsCodeVo.class);

            // 如果有，判断上一次发送时间和当前次发送时间是否过了60s
            //获取上一次发送时间,必须60S之后再发送
            Date lastSendTime = sendSmsCodeVo.getSendTime();
            if((now.getTime() - lastSendTime.getTime())/1000 < 60 ){
                throw new RuntimeException("发送频繁，请稍后重试");
            }
            //如果没有过期就获取上一次的验证码
            smsCodeValue = sendSmsCodeVo.getSmsCode();
        }else{
            // redis中没有验证码，重写生成一个随机的验证码4位
            smsCodeValue = StrUtils.getRandomString(4);
        }
        // 把手机验证码发送记录存储到Redis ：
        //把验证码发送记录封装成对象  验证码和生成时间
        SendSmsCodeVo sendSmsCodeVo = new SendSmsCodeVo(smsCodeValue, now);
        //把对象转成JSON存储到redis
        String sendSmsCodeVoJson = JSON.toJSONString(sendSmsCodeVo);
        AjaxResult imageCodeResult = redisFeignClient.setex(smsCodeKey, imageCodeProperties.getTimeout(), sendSmsCodeVoJson);
        if(!imageCodeResult.isSuccess()){
            throw new RuntimeException("验证码发送失败,缓存服务不可用");
        }

        //5.把验证码的内容进行发送到用户的手机 这里是测试所以在后台打印
        String messsage = "您的手机验证码为["+smsCodeValue+"]，请在5分钟内使用";
        System.out.println(messsage);
        HashMap<String, String> params = new HashMap<>();
        params.put("Uid","luo851036494");
        params.put("Key","d41d8cd98f00b204e980");
        params.put("smsMob",mobile);
        params.put("smsText",messsage);
        //发送
        HttpUtil.sendPost("http://utf8.api.smschinese.cn/",params);

        //6.Mysql存储发送记录
    }
}
